import { Component, OnInit, ViewChild, TemplateRef, OnDestroy } from '@angular/core'
import { Observable } from 'rxjs'
import { NzMessageService, NzModalService } from 'ng-zorro-antd'
import { ACLService } from '@delon/acl'
import { SettingsService } from '@delon/theme'

import { DetailBaseClass } from '@shared/classes/DetailBaseClass'
import { User, IUpdateUser, UserRole } from '@shared/interfaces/user'
import { PageService } from '@shared/services/page.service'
import { UserService } from 'app/routes/user/user.service'
import { UserAlinterService } from 'app/routes/user/user-alinter.service'
import { EUserType, ERoleType, EBizLevel } from '@shared/enums'
import { Router, ActivatedRoute } from '@angular/router'
import { DetailHeaderComponent } from '@shared/components/detail-header/detail-header.component'
import { StatusTextMap, UserTypeTextMap, IDetailHeaderTab } from '@shared/interfaces/common'
import { Validators } from 'app/utils/validator'
import { nicknameLength, emailReg, emailMaxLength } from 'app/utils/contraints'
import { IBiz } from '@shared/interfaces/biz'
import { I18NService } from '@core'
import { DataService } from '@shared/services/data.service'

@Component({
  selector: 'app-dashboard-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.less'],
  providers: [{ provide: UserService, useClass: UserAlinterService }],
})
export class UserProfileComponent extends DetailBaseClass<User> implements OnInit, OnDestroy {
  imgSrc = 'assets/images/centaur/base-info-pic/user.png'

  @ViewChild('tpUserRoles') tpUserRoles: TemplateRef<any>
  @ViewChild('tpControl') tpControl: TemplateRef<any>

  @ViewChild(DetailHeaderComponent) detailHeaderComponent: DetailHeaderComponent

  tabs: IDetailHeaderTab[] = [
    { text: this.trans('GENERAL.INFO.OTHER.SYSTEM_INFO'), url: './system' },
    { text: this.trans('GENERAL.INFO.OTHER.AUDIT_INFO'), url: './audit' },
  ]

  isViewCurrentUser = false
  userName: string
  userRoles$: Observable<UserRole[]>

  userRoleCompareFn = (o1: UserRole, o2: UserRole) => o1 && o2 ? o1.roleId === o2.roleId : o1 === o2

  constructor(
    public pageService: PageService,
    public userService: UserService,
    public msg: NzMessageService,
    public router: Router,
    public route: ActivatedRoute,
    public aclService: ACLService,
    private settingService: SettingsService,
    private modal: NzModalService,
    private message: NzMessageService,
    private i18n: I18NService,
    private dataService: DataService,
  ) {
    super(pageService)
  }

  ngOnInit() {
    this.getUser()
  }

  getUser() {
    this.userName = this.getUsername()
    if (this.userName) {
      this.loadDetailDataByUserName(this.userName)
      return
    }

    this.isViewCurrentUser = true
    this.loadDetailDataByUserName(this.settingService.user.username)
  }

  getUserRoles() {
    let type = 0
    switch (this.detailData.userType) {
      case EUserType.Institution: {
        type = ERoleType.Acquirer
        break
      }
      case EUserType.Agent: {
        type = ERoleType.Group
        break
      }
      case EUserType.Merchant: {
        type = ERoleType.Merchant
        break
      }
      case EUserType.Store: {
        type = ERoleType.Store
        break
      }
    }
    if (this.detailData.insCode) {
      this.userRoles$ = this.userService.getAcquirerRole(this.detailData.insCode, type)
    }
  }

  ngOnDestroy(): void {
    // Called once, before the instance is destroyed.
    // Add 'implements OnDestroy' to the class.
    this.pageService.triggerBaseEdit(false)
  }

  getUsername(): string {
    return this.route.snapshot.params['id']
  }

  initialData(user: User) {
    this.detailData = user
    if (!this.detailData.roles) {
      this.detailData.roles = []
    }
    this.userName = user.username
    this.initColumns()
    this.initialBaseColumns()
    this.loading = false
    this.initOtherTabs()
  }

  loadDetailDataByUserName(userName: string): void {
    this.userService.getOne(userName).subscribe(user => {
      if (!user) {
        this.msg.error('获取用户信息出错')
        return
      }
      this.initialData(user)
      this.dataService.setUser(user)
    })
  }

  initOtherTabs(): void {
    const { userType } = this.detailData
    if (userType !== EUserType.Institution) {
      this.tabs.pop()
    }
  }

  initialBaseColumns() {
    let roleName = '-'

    if (this.detailData && this.detailData.roles && this.detailData.roles.length) {
      roleName = this.detailData.roles[0].roleName
    }

    this.firstColumns = [
      {
        span: 8,
        index: 'username',
        label: 'USER.USERNAME',
        labelI18n: 'USER.USERNAME',
        value: this.detailData.username,
        disEditable: true,
      },
      {
        span: 8,
        index: 'nickName',
        label: 'USER.NAME',
        labelI18n: 'USER.NAME',
        value: this.detailData.nickName,
        validator: {
          funcs: [Validators.required, Validators.maxLength(nicknameLength)],
          errorTips: [
            this.trans('VALIDATION.REQUIRED', { name: this.trans('USER.NAME') }),
            this.trans('VALIDATION.MAX_LENGTH', { length: nicknameLength }),
          ],
        },
      },
      {
        span: 8,
        index: 'email',
        label: 'GENERAL.INFO.EMAIL',
        labelI18n: 'GENERAL.INFO.EMAIL',
        value: this.detailData.email,
        validator: {
          funcs: [Validators.required, Validators.maxLength(emailMaxLength), Validators.pattern(emailReg)],
          errorTips: [
            this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.EMAIL') }),
            this.trans('VALIDATION.MAX_LENGTH', { length: emailMaxLength }),
            this.trans('VALIDATION.PATTERN.EMAIL'),
          ],
        },
      },
    ]
    const userName = this.getUsername()
    // If userName found mean admin/ high level role user is viewing other profile.
    const span = userName ? 6 : 8

    this.secondColumns = [
      {
        span,
        index: 'userType',
        label: 'USER.USER_TYPE',
        labelI18n: 'USER.USER_TYPE',
        displayValue: this.trans(UserTypeTextMap[this.detailData.userType]),
        disEditable: true,
      },
      {
        span,
        index: 'userRole',
        value: roleName,
        label: 'USER.USER_ROLE',
        labelI18n: 'USER.USER_ROLE',
        template: this.tpUserRoles,
        pipe: () => {
          return this.detailData.roles && this.detailData.roles.length > 0 ? this.detailData.roles[0].roleName : ''
        },
        disEditable: this.isViewCurrentUser,
      },
      {
        span,
        index: 'status',
        label: 'GENERAL.INFO.STATUS',
        labelI18n: 'GENERAL.INFO.STATUS',
        displayValue: this.trans(StatusTextMap[this.detailData.status]),
        disEditable: true,
      },
    ]
    if (userName) {
      this.secondColumns.push({
        span: 6,
        label: 'GENERAL.INFO.OPERATION',
        labelI18n: 'GENERAL.INFO.OPERATION',
        template: this.tpControl,
        operate: true,
        disEditable: true,
        acl: ['api.put.camel.user.one.freeze', 'api.put.camel.user.one.unfreeze', 'api.delete.camel.user.one'],
      })
    }
  }

  freezeUserDialog(): void {
    this.modal.confirm({
      nzTitle: this.trans('GENERAL.NOTIFICATION.WARNING'),
      nzContent: this.trans('GENERAL.NOTIFICATION.USER_FREEZE_CONFIRM', {username: this.userName}),
      nzOnOk: this.freezeUser.bind(this),
    })
  }

  // 冻结用户
  freezeUser(): void {
    this.userService.freeze(this.userName).subscribe(
      values => {
        console.log(values)
        this.message.success(this.trans('GENERAL.NOTIFICATION.FREEZE_SUCCESS'))
        this.getUser()
      },
      err => {
        console.error(err)
        this.message.error(this.trans('GENERAL.NOTIFICATION.FREEZE_FAIL'))
      },
    )
  }

  // 解冻用户
  unfreezeUserDialog(): void {
    this.modal.confirm({
      nzTitle: this.trans('GENERAL.NOTIFICATION.WARNING'),
      nzContent: this.trans('GENERAL.NOTIFICATION.USER_UNFREEZE_CONFIRM', {username: this.userName}),
      nzOnOk: this.unfreezeUser.bind(this),
    })
  }

  unfreezeUser(): void {
    this.userService.unfreeze(this.userName).subscribe(
      values => {
        console.log(values)
        this.message.success(this.trans('GENERAL.NOTIFICATION.UNFREEZE_SUCCESS'))
        this.getUser()
      },
      err => {
        console.error(err)
        this.message.success(this.trans('GENERAL.NOTIFICATION.UNFREEZE_FAIL'))
      },
    )
  }

  // 刪除用户
  deleteUserDialog(): void {
    this.modal.confirm({
      nzTitle: this.trans('GENERAL.NOTIFICATION.WARNING'),
      nzContent: this.trans('GENERAL.NOTIFICATION.USER_DELETE_CONFIRM', {username: this.userName}),
      nzOnOk: this.deleteUser.bind(this),
    })
  }

  deleteUser(): void {
    this.userService.delete(this.userName).subscribe(
      values => {
        this.message.success(this.trans('GENERAL.NOTIFICATION.DELETE_SUCCESS'))
        const user = this.settingService.user
        switch (user.userType) {
          case EUserType.Institution:
          case EUserType.Agent:
          case EUserType.Merchant:
          case EUserType.Store:
            this.router.navigateByUrl(this.getCodeURL(this.detailData.userType))
            break
          default:
            this.router.navigate(['../'], { relativeTo: this.route })
        }
      },
      err => {
        console.error(err)
        this.message.error(this.trans('GENERAL.NOTIFICATION.DELETE_FAIL'))
      },
    )
  }

  // 通过要删除的用户类型获取跳转URL
  getCodeURL(userType: string): string {
    let URL = ''
    switch (userType) {
      case EUserType.Institution:
        URL = 'acquirers/' + this.detailData.insCode
        break
      case EUserType.Agent:
        URL = 'groups/' + this.detailData.agentCode
        break
      case EUserType.Merchant:
        URL = 'merchants/' + this.detailData.intMerCode
        break
      case EUserType.Store:
        URL = 'stores/' + this.detailData.intStoreCode
        break
      default: break
    }
    return '/biz/' + URL + '/users'
  }

  goEditPassword(): void {
    const username = this.getUsername()
    if (username) {
      this.router.navigate([`edit-password`], {
        queryParams: { username },
        relativeTo: this.route,
      })
    } else {
      this.router.navigate(['/dashboard/user/profile/edit-password'], {
        relativeTo: this.route,
      })
    }
  }

  triggerBaseEdit(): void {
    this.copiedDetailData = this.copyDetailData(this.detailData)
    // 如果是编辑他们的用户信息，是需要载入角色列表的
    if (!this.isViewCurrentUser) {
      this.getUserRoles()
    }
    this.pageService.triggerBaseEdit(true)
  }

  cancelBase(): void {
    this.detailData = this.copiedDetailData
    this.clearColumnsErrorTips()
    this.initColumns()
    this.pageService.triggerBaseEdit(false)
  }

  saveBase(): void {
    if (!this.checkEditValidation()) {
      this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
      return
    }
    try {
      this.detailHeaderComponent.hideButtons()
      this.pageService.triggerBaseEdit(false)
      this.updateColumns()
      const { username, ...user } = this.detailData
      const params: IUpdateUser = {
        nickName: user.nickName,
        email: user.email,
        roleIDs: user.roles.map(role => role.roleId),
        status: user.status,
        version: user.version,
      }
      this.userService.update(username, params).subscribe(data => {
        const { roles } = this.detailData
        this.detailData = { ...data, roles }
        this.initColumns()
        this.clearColumnsErrorTips()
        this.msg.success(this.trans('GENERAL.NOTIFICATION.UPDATE_SUCCESS'))
      })
    } catch (err) {
      this.msg.error(this.trans('GENERAL.NOTIFICATION.UPDATE_FAIL'), err.message)
    }
  }

  hasBtnSeparator(): boolean {
    const canLock = this.aclService.canAbility('api.put.camel.user.one.freeze')
    const canUnlock = this.aclService.canAbility('api.put.camel.user.one.unfreeze')
    const canDelete = this.aclService.canAbility('api.delete.camel.user.one')
    return canDelete && (canLock || canUnlock)
  }

  trans(key: string, params?: Object): string {
    if (!key) {
      return ''
    }
    return this.i18n.fanyi(key, params)
  }
}
